home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Complete Linux
/
Complete Linux.iso
/
xwindows
/
demos
/
xfract_1.z
/
xfract_1
/
xfractint-1.06
/
lsys.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-28
|
21KB
|
895 lines
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#ifdef __TURBOC__
#include <alloc.h>
#else
#include <malloc.h>
#endif
#include "fractint.h"
#include "prototyp.h"
#define size ssize
/* Needed for use of asm -- helps decide which pointer to function
* to put into the struct lsys_cmds.
*/
extern int cpu;
extern int fpu;
extern int debugflag;
extern int xdots,ydots;
extern int colors;
extern char LFileName[];
extern char LName[];
extern double param[];
extern int overflow;
struct lsys_cmd {
char ch;
void (*f)(long n);
long n;
};
static double _fastcall getnumber(char far **);
static struct lsys_cmd far * _fastcall findsize(struct lsys_cmd far *,struct lsys_cmd far **,int);
static int _fastcall findscale(struct lsys_cmd far *, struct lsys_cmd far **, int);
static struct lsys_cmd far * _fastcall drawLSys(struct lsys_cmd far *, struct lsys_cmd far **, int);
static int _fastcall readLSystemFile(char *);
static void _fastcall free_rules_mem(void);
static int _fastcall save_rule(char *,char far **);
static struct lsys_cmd far *SizeTransform(char far *s);
static struct lsys_cmd far *DrawTransform(char far *s);
static void free_lcmds();
static long aspect; /* aspect ratio of each pixel, ysize/xsize */
/* Some notes to Adrian from PB, made when I integrated with v15:
printfs changed to work with new user interface
bug at end of readLSystemFile, the line which said rulind=0 fixed
to say *rulind=0
the calloc was not worthwhile, it was just for a 54 byte area, cheaper
to keep it as a static; but there was a static 201 char buffer I
changed to not be static
use of strdup was a nono, caused problems running out of space cause
the memory allocated each time was never freed; I've changed to
use far memory and to free when done
*/
long sins[50];
long coss[50];
/* dmaxangle is maxangle - 1. */
char maxangle,dmaxangle,curcolor;
long size;
unsigned long realangle;
long xpos,ypos;
char counter,angle,reverse,stackoflow;
long lsys_Xmin, lsys_Xmax, lsys_Ymin, lsys_Ymax;
/* Macro to take an FP number and turn it into a
* 16/16-bit fixed-point number.
*/
#define FIXEDMUL 524288L
#define FIXEDPT(x) ((long) (FIXEDMUL * (x)))
/* The number by which to multiply sines, cosines and other
* values with magnitudes less than or equal to 1.
* sins and coss are a 3/29 bit fixed-point scheme (so the
* range is +/- 2, with good accuracy. The range is to
* avoid overflowing when the aspect ratio is taken into
* account.
*/
#define FIXEDLT1 536870912.0
/* Multiply by this number to convert an unsigned 32-bit long
* to an angle from 0-2PI.
*/
#define ANGLE2DOUBLE (2*PI / 4294967296.)
static int ispow2(long n)
{
return (n == (n & -n));
}
#ifdef XFRACT
static void lsys_doplus(long n)
{
if (reverse) {
if (++angle == maxangle)
angle = 0;
}
else {
if (angle)
angle--;
else
angle = dmaxangle;
}
}
#endif
#ifdef XFRACT
/* This is the same as lsys_doplus, except maxangle is a power of 2. */
static void lsys_doplus_pow2(long n)
{
if (reverse) {
angle++;
angle &= dmaxangle;
}
else {
angle--;
angle &= dmaxangle;
}
}
#endif
#ifdef XFRACT
static void lsys_dominus(long n)
{
if (reverse) {
if (angle)
angle--;
else
angle = dmaxangle;
}
else {
if (++angle == maxangle)
angle = 0;
}
}
#endif
#ifdef XFRACT
static void lsys_dominus_pow2(long n)
{
if (reverse) {
angle--;
angle &= dmaxangle;
}
else {
angle++;
angle &= dmaxangle;
}
}
#endif
static void lsys_doslash(long n)
{
if (reverse)
realangle -= n;
else
realangle += n;
}
#ifdef XFRACT
#define lsys_doslash_386 lsys_doslash
#endif
static void lsys_dobslash(long n)
{
if (reverse)
realangle += n;
else
realangle -= n;
}
#ifdef XFRACT
#define lsys_dobslash_386 lsys_dobslash
#endif
static void lsys_doat(long n)
{
size = multiply(size, n, 19);
}
#ifdef XFRACT
#define lsys_doat_386 lsys_doat
#endif
static void lsys_dopipe(long n)
{
angle += maxangle / 2;
angle %= maxangle;
}
#ifdef XFRACT
static void lsys_dopipe_pow2(long n)
{
angle += maxangle >> 1;
angle &= dmaxangle;
}
#endif
#ifdef XFRACT
static void lsys_dobang(long n)
{
reverse = ! reverse;
}
#endif
static void lsys_dosizedm(long n)
{
double angle = (double) realangle * ANGLE2DOUBLE;
double s, c;
long fixedsin, fixedcos;
FPUsincos(&angle, &s, &c);
fixedsin = (long) (s * FIXEDLT1);
fixedcos = (long) (c * FIXEDLT1);
xpos += multiply(multiply(size, aspect, 19), fixedcos, 29);
ypos += multiply(size, fixedsin, 29);
/* xpos+=size*aspect*cos(realangle*PI/180); */
/* ypos+=size*sin(realangle*PI/180); */
if (xpos>lsys_Xmax) lsys_Xmax=xpos;
if (ypos>lsys_Ymax) lsys_Ymax=ypos;
if (xpos<lsys_Xmin) lsys_Xmin=xpos;
if (ypos<lsys_Ymin) lsys_Ymin=ypos;
}
static void lsys_dosizegf(long n)
{
xpos += multiply(size, (long) coss[angle], 29);
ypos += multiply(size, (long) sins[angle], 29);
/* xpos+=size*coss[angle]; */
/* ypos+=size*sins[angle]; */
if (xpos>lsys_Xmax) lsys_Xmax=xpos;
if (ypos>lsys_Ymax) lsys_Ymax=ypos;
if (xpos<lsys_Xmin) lsys_Xmin=xpos;
if (ypos<lsys_Ymin) lsys_Ymin=ypos;
}
#ifdef XFRACT
#define lsys_dosizegf_386 lsys_dosizegf
#endif
static void lsys_dodrawd(long n)
{
double angle = (double) realangle * ANGLE2DOUBLE;
double s, c;
long fixedsin, fixedcos;
int lastx, lasty;
FPUsincos(&angle, &s, &c);
fixedsin = (long) (s * FIXEDLT1);
fixedcos = (long) (c * FIXEDLT1);
lastx=(int) (xpos >> 19);
lasty=(int) (ypos >> 19);
xpos += multiply(multiply(size, aspect, 19), fixedcos, 29);
ypos += multiply(size, fixedsin, 29);
/* xpos+=size*aspect*cos(realangle*PI/180); */
/* ypos+=size*sin(realangle*PI/180); */
draw_line(lastx,lasty,(int)(xpos >> 19),(int)(ypos>>19),curcolor);
}
static void lsys_dodrawm(long n)
{
double angle = (double) realangle * ANGLE2DOUBLE;
double s, c;
long fixedsin, fixedcos;
FPUsincos(&angle, &s, &c);
fixedsin = (long) (s * FIXEDLT1);
fixedcos = (long) (c * FIXEDLT1);
/* xpos+=size*aspect*cos(realangle*PI/180); */
/* ypos+=size*sin(realangle*PI/180); */
xpos += multiply(multiply(size, aspect, 19), fixedcos, 29);
ypos += multiply(size, fixedsin, 29);
}
static void lsys_dodrawg(long n)
{
xpos += multiply(size, (long) coss[angle], 29);
ypos += multiply(size, (long) sins[angle], 29);
/* xpos+=size*coss[angle]; */
/* ypos+=size*sins[angle]; */
}
#ifdef XFRACT
#define lsys_dodrawg_386 lsys_dodrawg
#endif
static void lsys_dodrawf(long n)
{
int lastx = (int) (xpos >> 19);
int lasty = (int) (ypos >> 19);
xpos += multiply(size, (long) coss[angle], 29);
ypos += multiply(size, (long) sins[angle], 29);
/* xpos+=size*coss[angle]; */
/* ypos+=size*sins[angle]; */
draw_line(lastx,lasty,(int)(xpos>>19),(int)(ypos>>19),curcolor);
}
static void lsys_dodrawc(long n)
{
curcolor = ((int) n) % colors;
}
static void lsys_dodrawgt(long n)
{
curcolor -= n;
if ((curcolor &= colors-1) == 0)
curcolor = colors-1;
}
static void lsys_dodrawlt(long n)
{
curcolor += n;
if ((curcolor &= colors-1) == 0)
curcolor = 1;
}
static double _fastcall getnumber(char far **str)
{
char numstr[30];
float ret;
int i,root,inverse;
root=0;
inverse=0;
strcpy(numstr,"");
(*str)++;
switch (**str)
{
case 'q':
root=1;
(*str)++;
break;
case 'i':
inverse=1;
(*str)++;
break;
}
switch (**str)
{
case 'q':
root=1;
(*str)++;
break;
case 'i':
inverse=1;
(*str)++;
break;
}
i=0;
while (**str<='9' && **str>='0' || **str=='.')
{
numstr[i++]= **str;
(*str)++;
}
(*str)--;
numstr[i]=0;
ret=atof(numstr);
if (root)
ret=sqrt(ret);
if (inverse)
ret = 1/ret;
return ret;
}
static struct lsys_cmd far * _fastcall findsize(struct lsys_cmd far *command, struct lsys_cmd far **rules, int depth)
{
struct lsys_cmd far **rulind;
int tran;
i